﻿using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;
using System.Linq.Expressions;
using System.Web.Security;
using System.Security.Principal;

namespace Buggy.Web
{
    public class BuggyDataService : DataService<BuggyDataEntities>
    {
        // This method is called only once to initialize service-wide policies.
        public static void InitializeService(DataServiceConfiguration config)
        {
            // TODO: set rules to indicate which entity sets and service operations are visible, updatable, etc.
            // Examples:
            config.SetEntitySetAccessRule("Categories", EntitySetRights.AllRead);
            config.SetEntitySetAccessRule("Bugs", EntitySetRights.All);
            config.SetEntitySetAccessRule("BugComments", EntitySetRights.All);
            //config.SetServiceOperationAccessRule("Login", ServiceOperationRights.All);
            //config.SetServiceOperationAccessRule("Logout", ServiceOperationRights.All);
            //config.SetServiceOperationAccessRule("TestFunction", ServiceOperationRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }

        [QueryInterceptor("Bugs")]
        public Expression<Func<Bugs, bool>> OnQueryBugs()
        {				
	        if (!IsCurrentUserAuthenticated())
		        return o => false;

	        Users currentUser = getCurrentUser();
	        if (currentUser == null)
		        return o => false;

	        var bugsIds = getBugsIDsByUser(currentUser);

	        return o => bugsIds.Contains(o.id);
        }

		[ChangeInterceptor("Bugs")]
		public void OnChangeBugs(Bugs bugs, UpdateOperations operations)
		{
			if (!IsCurrentUserAuthenticated())
				throw new DataServiceException(400, "user is not authenticated");
			Users currentUser = getCurrentUser();
			if (currentUser == null)
				throw new DataServiceException(400, "no user with current name in database");
			if (!isBugRelateToUser(bugs, currentUser))
				throw new DataServiceException(400, "user can't change this bug");
		}

		protected bool IsCurrentUserAuthenticated()
		{
			return (HttpContext.Current.User.Identity.IsAuthenticated);
		}

		protected string getCurrentUsername()
		{
			return (HttpContext.Current.User.Identity.Name);
		}

		protected Users getCurrentUser()
		{
			string userName = getCurrentUsername();
			var users = from user in this.CurrentDataSource.Users
						where user.login == userName
						select user;
			if (users.Count() == 0)					
				return null;
			else return users.First();
		}

		protected bool isBugRelateToUser(Bugs bug, Users user)
		{
			var res = from bugOnUser in this.CurrentDataSource.BugsOnUsers
					  where ((bugOnUser.bugId == bug.id) && (bugOnUser.userId == user.id))
					  select bugOnUser;
			return (res.Count() == 1);
		}

		protected IQueryable<int> getBugsIDsByUser(Users currentUser)
		{
			return from bugOnUser in this.CurrentDataSource.BugsOnUsers
				   where bugOnUser.userId == currentUser.id
				   select bugOnUser.bugId;
		}

		/*
		[WebGet]
		public void Login(string login, string password)
		{
			// Log the user into the site
			FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
				1,
				//intUser.ToString(),
				login,
				DateTime.Now,
				DateTime.Now.AddDays(30),
				false,
				"Role One",
				FormsAuthentication.FormsCookiePath);

			// Encrypt the ticket.
			string encTicket = FormsAuthentication.Encrypt(ticket);

			// Create the cookie.
			HttpContext.Current.Response.Cookies.Add(new HttpCookie(FormsAuthentication.FormsCookieName, encTicket));
			//return new List<string>() { encTicket }; //debug
		}

		[WebGet]
		//[SingleResult]
		public void Logout()
		{
			FormsAuthentication.SignOut();
			//return "OK";
		}
			
		[WebGet]
		[SingleResult]
		public void TestFunction(string testinput, string testinput2)
		{
			//return new List<string> { "Test OK!" }.AsEnumerable<string>();
			//return "OK";
			//HttpContext.Current.Response.
		}
		*/
	}
}
